
#include <protocol.h>
#include "dp_process.h"

tp_driver_t tp_dev;

extern VOID upload_device_switch_status(BOOL_T state);
extern VOID upload_device_led_status(BOOL_T state);
extern VOID upload_device_speed_status(UINT8_T val);

static UINT8_T crc_sum8(UINT8_T *buff, UINT8_T len);
static UINT8_T tp_recv_drv_state(UINT8_T* buff, UINT8_T len); // 设备状态 
static UINT8_T tp_recv_key_single(UINT8_T* buff, UINT8_T len); // 触发配网状态 转速功率上报
static UINT8_T tp_recv_chenge_update(UINT8_T* buff, UINT8_T len); // 变化上报
static UINT8_T tp_recv_mix_fields_update(UINT8_T* buff, UINT8_T len); // 混合在一起上报
static UINT8_T tp_recv_null(UINT8_T* buff, UINT8_T len) {  return 0; }

typedef UINT8_T (*tp_function)(UINT8_T* buff, UINT8_T len);
tp_function list_cmd_function[] = 
{
    tp_recv_null,
    tp_recv_drv_state,
    tp_recv_key_single,
    tp_recv_chenge_update,
    tp_recv_mix_fields_update,
};

/**
 * 设备状态 
 */
static UINT8_T tp_recv_drv_state(UINT8_T* buff, UINT8_T len)
{
    /* led灯数据上报 */
    if(buff[0] == 0x01) // 关灯
    {
        tp_dev.led_sta = 0x00;
        tp_dev.flag_change |= 0x01;
    }
    else if(buff[0] == 0x02) // 开灯
    {
        tp_dev.led_sta = 0x01;
        tp_dev.flag_change |= 0x01;
    }

    /* 开关机数据上报 */
    if(buff[1] == 0x01) // 关机
    {
        tp_dev.on_push = 0x00;
        tp_dev.flag_change |= 0x02;
    }
    else if(buff[1] == 0x02) // 开机
    {
        tp_dev.on_push = 0x01;
        tp_dev.flag_change |= 0x02;
    }

    /* 转速值 */
    tp_dev.speed_power = buff[2];
    tp_dev.flag_change |= 0x04;

    return 0;
}

/**
 * 触发配网状态 转速功率上报
 */
static UINT8_T tp_recv_key_single(UINT8_T* buff, UINT8_T len)
{
    switch (buff[0])
    {
        case 0x01:
            tp_dev.config_net = 0x01; // 配置网络
            tuya_iot_wf_gw_unactive();
        break;
        case 0x02:
            tp_dev.config_net = 0x02; // 重启设备
        break;
        case 0x04: 
            tp_dev.on_push = 0x00; // 设备关机
            tp_dev.flag_change |= 0x02;
        break;
        case 0x08:
            tp_dev.on_push = 0x01; // 设备开机
            tp_dev.flag_change |= 0x02;
        break;
    }

    /* 转速值 */
    tp_dev.speed_power = buff[1];
    tp_dev.flag_change |= 0x04;

    return 0;
}

/**
 * 变化上报
 */
static UINT8_T tp_recv_chenge_update(UINT8_T* buff, UINT8_T len)
{
    /* 转速值 */
    tp_dev.speed_power = buff[0];
    tp_dev.flag_change |= 0x04;

    /* led灯数据上报 */
    if(buff[1] == 0x01) // 开灯
    {
        tp_dev.led_sta = 0x01;
        tp_dev.flag_change |= 0x01;
    }
    else// 关灯
    {
        tp_dev.led_sta = 0x00;
        tp_dev.flag_change |= 0x01;        
    }

    /* 故障码显示 */
    if(buff[2] != 0)
    {
        tp_dev.filed_bit = buff[2];   
        tp_dev.flag_change |= 0x08;         
    }

    return 0;
}

/**
 * 混合成一帧数据上报
 */
static UINT8_T tp_recv_mix_fields_update(UINT8_T* buff, UINT8_T len)
{
    /* 更新转速值 */
    if(buff[0] > 100)
    {
        buff[0] = 100;        
    }
    if(tp_dev.speed_power != buff[0])
    {
        tp_dev.speed_power = buff[0];    
        upload_device_speed_status(tp_dev.speed_power);  
    }

    /* 更新LED状态显示 */
    UINT8_T temp = buff[1]&0x01;
    if(temp != tp_dev.led_sta)
    {
        tp_dev.led_sta = temp;
        upload_device_led_status(tp_dev.led_sta);
    }

    /* 更新开关机显示 */
    temp = ((buff[1] >> 1)&0x01);
    if(temp != tp_dev.on_push)
    {
        tp_dev.on_push = temp;
        upload_device_switch_status(tp_dev.on_push);
    }

    /* 故障码显示 */
    if(buff[2] != 0)
    {
        tp_dev.filed_bit = buff[2];      
    }

    /* 配网指令 */
    if(buff[3] == 0x01)
    {
        tuya_iot_wf_gw_unactive();
    }
    else
    {
        ;//upload_device_all_status();        
    }

    return 0;
}

/////////////////////////////////////////////////////////////////////////////////////////
//       以下为数据发送帧
////////////////////////////////////////////////////////////////////////////////////////
/**
 * 更新设备状态 
 */
UINT8_T tp_send_drv_state(UINT8_T led_sta, UINT8_T on_push, UINT8_T speed)
{
    UINT8_T len = 0;
    UINT8_T buff[MAX_DATE_LEN] = {0};
    buff[len++] = FRAME_HEADER_1;
    buff[len++] = FRAME_HEADER_2;
    buff[len++] = 0x05;
    buff[len++] = 0x01;
    buff[len++] = led_sta;
    buff[len++] = on_push;
    buff[len++] = speed;
    buff[len++] = crc_sum8(&buff[2], (len - 2));

    tal_uart_write(UART_NUM_0, buff, len);
    return 0;
}

/**
 * 回复iot状态 
 */
UINT8_T tp_send_drv_single(UINT8_T net_sta)
{
    UINT8_T len = 0;
    UINT8_T buff[MAX_DATE_LEN] = {0};
    buff[len++] = FRAME_HEADER_1;
    buff[len++] = FRAME_HEADER_2;
    buff[len++] = 0x04;
    buff[len++] = 0x02;
    buff[len++] = net_sta;
    buff[len++] = 0x00;
    buff[len++] = crc_sum8(&buff[2], (len - 2));
    tal_uart_write(UART_NUM_0, buff, len);
    return 0;
}

/**
 * 回复iot状态 
 */
UINT8_T tp_send_chenge_state(void)
{
    UINT8_T len = 0;
    UINT8_T buff[MAX_DATE_LEN] = {0};
    buff[len++] = FRAME_HEADER_1;
    buff[len++] = FRAME_HEADER_2;
    buff[len++] = 0x04;
    buff[len++] = 0x02;
    buff[len++] = 0x00;
    buff[len++] = 0x00;
    buff[len++] = crc_sum8(&buff[2], (len - 2));
    tal_uart_write(UART_NUM_0, buff, len);
    return 0;
}

/**
 * 下发数据更新
 *   UINT8_T led_sta : led状态
 *   UINT8_T on_push : 开关机状态
 *   UINT8_T speed : 速度控制
 *   UINT8_T clear_err : 清除错误
 */
UINT8_T tp_send_mix_fields_update(UINT8_T led_sta, \ 
                                  UINT8_T on_push, \
                                  UINT8_T speed, \
                                  UINT8_T clear_err)
{
    UINT8_T len = 0;
    UINT8_T buff[MAX_DATE_LEN] = {0};
    buff[len++] = FRAME_HEADER_1;
    buff[len++] = FRAME_HEADER_2;
    buff[len++] = 0x06;
    buff[len++] = 0x01;
    if(led_sta == 0)
        led_sta = 1;
    else if(led_sta == 1)
        led_sta = 2;
    else
        led_sta = 0;
    buff[len++] = led_sta;
    if(on_push == 0)
        on_push = 1;
    else if(on_push == 1)
        on_push = 2;
    else
        on_push = 0;
    buff[len++] = on_push;
    buff[len++] = speed;
    buff[len++] = clear_err;
    buff[len++] = crc_sum8(&buff[2], 6);
    tal_uart_write(UART_NUM_0, buff, len);
    return 0;
}

///////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////

/**
 * 校验和
 */
static UINT8_T crc_sum8(UINT8_T *buff, UINT8_T len)
{
    UINT8_T crc_sum = 0;
    for(UINT8_T index = 0; index < len; index++)
    {
        crc_sum = crc_sum + buff[index];
    }
    return crc_sum;
};

/**
*   按照单个字节解析接收数据
*/
static void tp_receive_analysis(UINT8_T byte)
{
    #define FRAME_SIZE 16U

    static UINT8_T number = 0;
    static UINT8_T pos = 0;
    static UINT8_T buff[FRAME_SIZE];
    UINT8_T cal_crc = 0;

    LAB_ANALYSIS:
    switch (number)
    {
        case 0:  /* 找帧头1 */
        if(FRAME_HEADER_1 == byte)
        {
            number = 1;
        } 
        break;
        case 1: /* 找帧头2 */
        if(FRAME_HEADER_2 == byte)
        {
            number = 2;
            pos = 0;
        }
        else
        {
            number = 0;
            goto LAB_ANALYSIS;
        }
        break;
        case 2: /* 获取长度 */
            buff[pos++] = byte;
            number = 3;
        break;
        case 3: /* 获取类型 */
            buff[pos++] = byte;
            number = 4;
        break;
        case 4: /* 获取数据 */
            buff[pos++] = byte;
            if(pos >= FRAME_SIZE)
            {
                number = 0;
            }
            if(pos == (buff[0] + 1))
            {
                UINT8_T recv_crc = byte;
                cal_crc = crc_sum8((UINT8_T*)(buff), (pos - 1));
                if((cal_crc == recv_crc) && (buff[1] < sizeof(list_cmd_function)))
                {
                    list_cmd_function[buff[1]](&buff[2], (buff[0] - 2));                        
                }
                number = 0;
            }
        break;
    default:
        break;
    }
}

/**
 * 堵塞接收串口数据
 */
STATIC VOID tp_rx_thread(PVOID_T args)
{
    UINT8_T data[MAX_DATE_LEN];
    for (;;) 
    {
        UINT32_T len = tal_uart_read(UART_NUM_0, data, sizeof(data));
        if(len != 0)
        {   
            for (UINT32_T i = 0; i < len; i++)
            {
                tp_receive_analysis(data[i]);
                TAL_PR_NOTICE(" data[%d] = %d.", i , data[i]);   
            }
        }
    }
    tal_uart_deinit(UART_NUM_0);
    return;
}

/**
 * 与设备通信初始化
 */
void tp_init(void)
{
    OPERATE_RET op_ret;

    // 串口初始化
    STATIC TAL_UART_CFG_T sg_uart_cfg = {
        .rx_buffer_size = MAX_DATE_LEN,
        .open_mode = O_BLOCK,
        .base_cfg = {
            .baudrate = 9600,
            .parity = TUYA_UART_PARITY_TYPE_NONE,
            .databits = TUYA_UART_DATA_LEN_8BIT,
            .stopbits = TUYA_UART_STOP_LEN_1BIT,
            .flowctrl = TUYA_UART_FLOWCTRL_NONE,
        },
    };
    tal_uart_init(UART_NUM_0, &sg_uart_cfg);

    // 初始化线程
    THREAD_HANDLE uart_task_handle;
    THREAD_CFG_T thread_cfg = 
    {
        .thrdname = "tp_rx_thread",
        .priority = THREAD_PRIO_3,
        .stackDepth = 2048,
    };
    op_ret = tal_thread_create_and_start(&uart_task_handle, \
                                          NULL, \
                                          NULL, \
                                          tp_rx_thread, \
                                          NULL, \
                                          &thread_cfg);

    TAL_PR_NOTICE("protocol start running.");    

    if(op_ret != OPRT_OK)
    {
        PR_ERR("thread_init_fail, err code: %d", op_ret);
        return;
    }
}
